package com.miyu.common.utils.commonUtils;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.miyu.common.utils.magic.GetBeanUtil;
import com.miyu.common.utils.redis.redisUtils.manager.Knife4jRedisManager;
import com.miyu.common.utils.redis.redisUtils.util.RedisListUtil;
import com.miyu.common.utils.redis.redisUtils.util.RedisValUtil;

import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;


public class Rediscache {

    static Knife4jRedisManager knife4jRedisManager = GetBeanUtil.getBeanByClass(Knife4jRedisManager.class);//list
    static RedisListUtil rvl = GetBeanUtil.getBeanByClass(RedisListUtil.class);//list
    static RedisValUtil rsv = GetBeanUtil.getBeanByClass(RedisValUtil.class);//val

    private static int defaultDB=0;

    /**
     * 是否存在key值
     * @param key
     * @return
     */
    public static  boolean hasKey(String key){
        return rvl.hasKey(key);
    }
    public static  boolean hasKey(int dbIndex,String key){
        return rvl.hasKey(dbIndex,key);
    }
    /**
     * JSONObject
     * 在json中添加元元素 本身是果JSON元素 key相同覆盖处理
     * value 数据 key:{}
     * @return
     */
    public static boolean set(String key, JSONObject value){
        return set(defaultDB,key ,value);
    }
    public static boolean set(int dbIndex ,String key, JSONObject value){
        try {
            if (knife4jRedisManager.isEnableRedis(dbIndex)) {
                knife4jRedisManager.redisTemplate(dbIndex).opsForValue().set(key, value);
            }
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存放入
     * @param key   键
     * @param value 值
     * @return true成功 false失败
     */
    public static boolean set(String key, Object value) {
        return  set(defaultDB , key ,value);
    }
    public static boolean set(int dbIndex ,String key, Object value) {
        try {
            if(knife4jRedisManager.isEnableRedis(dbIndex)) {
                knife4jRedisManager.redisTemplate(dbIndex).opsForValue().set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 使用JSONObject格式处理
     * 获取 String 类型 key-value
     * @param key 键
     * @return
     */
    public static Object get(String key) {
        return get(defaultDB ,key);
    }
    public static Object get(int dbIndex ,String key) {
        Object result =null;

        if(knife4jRedisManager.isEnableRedis(dbIndex)&&hasKey(dbIndex,key)) {
            result= knife4jRedisManager.redisTemplate(dbIndex).opsForValue().get(key);
        }
        return result == null ? null : String.valueOf(result) ;
    }

    /**
     * 获取单对象 redis<String,Clazz>
     * @param key
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T get(String key , Class<T> clazz) {
        return  get(defaultDB ,key , clazz);
    }
    public static <T> T get(int dbIndex ,String key , Class<T> clazz) {
        Object o=null;
        if(knife4jRedisManager.isEnableRedis(dbIndex)) {
            o = knife4jRedisManager.redisTemplate(dbIndex).opsForValue().get(key);
        }
        if(o instanceof JSONObject){
            JSONObject jo = (JSONObject)o;
            T t = jo.toJavaObject(clazz);
            return t;
        }
        T t = JSONObject.parseObject(JSONObject.toJSONString(o), clazz);
        return t;
    }
    /**
     * 带失效时间设置
     *
     * @param key     键
     * @param value   值
     * @param timeout 失效时间（秒）
     */
    public static void set(String key, Object value, long timeout) {
        set(defaultDB , key ,value ,timeout);
    }
    public static void set(int dbIndex ,String key, Object value, long timeout) {
        if(knife4jRedisManager.isEnableRedis(dbIndex)) {
            knife4jRedisManager.redisTemplate(dbIndex).opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
        }
    }

    /**
     * 递增
     *
     * @param key   键
     * @param delta 要增加几(大于0)
     * @return
     */
    public static long incr(String key, long delta) {
        return incr(defaultDB , key , delta);
    }
    public static long incr(int dbIndex ,String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return knife4jRedisManager.redisTemplate(dbIndex).opsForValue().increment(key, delta);
    }

    public static long incrFiled(String key, String filed) {
        return incrFiled(defaultDB , key , filed);
    }
    public static long incrFiled(int dbIndex ,String key, String filed) {
        return knife4jRedisManager.redisTemplate(dbIndex).opsForHash().increment(key, filed, 1);
    }

    /**
     * 递减
     *
     * @param key   键
     * @param delta 要减少几(小于0)
     * @return
     */
    public static long decr(String key, long delta) {
        return decr(defaultDB , key ,delta);
    }
    public static long decr(int dbIndex ,String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return knife4jRedisManager.redisTemplate(dbIndex).opsForValue().increment(key, -delta);
    }

    /**
     * 在list集合最前面插入数据
     * @param key  需要操作的key
     * @param values 待添加的值
     * @return
     */
    public static Long insert(String key, Object ... values) {
        return insert(defaultDB ,key , values);
    }
    public static Long insert(int dbIndex ,String key, Object ... values) {
        return knife4jRedisManager.redisTemplate(dbIndex).opsForList().leftPushAll(key ,values);

    }
    public static Long insert(String key, Collection<?>... values) {
        return insert(defaultDB , key ,values);
    }
    public static Long insert(int dbIndex ,String key, Collection<?>... values) {
        return knife4jRedisManager.redisTemplate(dbIndex).opsForList().leftPushAll(key ,values);
    }

    /**
     * 在list集合最后面追加数据
     * @param key  需要操作的key
     * @param values 待添加的值
     * @return
     */
    public static Long append(String key, Object... values) {
        return append(defaultDB , key , values);
    }
    public static Long append(int dbIndex ,String key, Object... values) {
        return knife4jRedisManager.redisTemplate(dbIndex).opsForList().rightPushAll(key, values);
    }
    /**
     * 在指定索引处添加数据，如果存在则为替换
     * @param key 需要操作的key
     * @param index 指定索引，该索引从0开始
     * @param value 待添加的值
     */
    public static void set(String key, long index, Object value) {
        set(defaultDB , key ,index,value);
    }
    public static void set(int dbIndex ,String key, long index, Object value) {
        knife4jRedisManager.redisTemplate(dbIndex).opsForList().set(key , index ,value);
    }

    /**
     * 取出某个范围的集合数据
     * @param key 需要操作的key
     * @param start 集合起点，索引从0开始
     * @param end 集合终点，若为-1则表示取出所有
     * @return 返回所有对象
     */
    public static <T> List<T> getList(String key, long start, long end , Class<T> t) {
        return getList(defaultDB , key , start , end , t);
    }
    public static <T> List<T> getList(int dbIndex ,String key, long start, long end , Class<T> t) {
        //此处返回的真实类型是JSONArray
        List<T> list = knife4jRedisManager.redisTemplate(dbIndex).opsForList().range(key, start, end);
        return list;
    }

    /**
     * 数据直接返回JSONArray
     * @param dbIndex
     * @param key
     * @return
     */
    public static JSONArray getJSONArray(int dbIndex , String key){
        JSONArray rs = new JSONArray();
        List range = knife4jRedisManager.redisTemplate(dbIndex).opsForList().range(key, 0, -1);
        rs  = JSONArray.parseArray(range.toString());
        return rs;
    }
    /**
     * 获取redis集合类型所有元素
     * @param key
     * @param t
     * @param <T>
     * @return
     */
    public static  <T> List<T> getListAll(String key , Class<T> t) {
        return getListAll(defaultDB , key , t);
    }
    public static <T> List<T> getListAll(int dbIndex ,String key , Class<T> t) {
        List<T> list = knife4jRedisManager.redisTemplate(dbIndex).opsForList().range(key, 0, -1);
        return list;
    }

    /**
     * 返回list集合的大小
     * @param key 需要操作的key
     * @return
     */
    public static Long size(String key) {
        return size(defaultDB , key);
    }
    public static Long size(int dbIndex ,String key) {
        return knife4jRedisManager.redisTemplate(dbIndex).opsForList().size(key);
    }

    /**
     * 返回某个索引处的数据
     * @param key  需要操作的key
     * @param index 索引 下标从0开始
     * @return
     */
    public static <T> T getByIndex(String key , long index , Class<T> clazz) {
        return getByIndex(defaultDB , key , index , clazz);
    }
    public static <T> T getByIndex(int dbIndex ,String key , long index , Class<T> clazz) {
        Object obj = knife4jRedisManager.redisTemplate(dbIndex).opsForList().index(key, index);
        return JSONObject.parseObject(String.valueOf(obj) , clazz);
    }

    /**
     * 弹出最左边数据，弹出后集合将不存在该数据
     * @param key
     * @return
     */
    public static <T> T popLeft(String key , Class<T> clazz) {
        return  popLeft(defaultDB , key , clazz);
    }
    public static <T> T popLeft(int dbIndex ,String key , Class<T> clazz) {
        Object obj = knife4jRedisManager.redisTemplate(dbIndex).opsForList().leftPop(key);
        if(obj == null){
            return null;
        }
        return JSONObject.parseObject(String.valueOf(obj) , clazz);
    }

    /**
     * 弹出最右边数据，弹出后集合将不存在该数据
     * @param key
     * @return
     */
    public static <T> T  popRight(String key , Class<T> clazz) {
        return popRight(defaultDB , key , clazz);
    }
    public static <T> T  popRight(int dbIndex ,String key , Class<T> clazz) {
        Object obj = knife4jRedisManager.redisTemplate(dbIndex).opsForList().rightPop(key);
        if(obj == null){
            return null;
        }
        return JSONObject.parseObject(String.valueOf(obj) , clazz);
    }

    /**
     * 直接删除数据，该数据从某个位置开始
     * @param key   删除的key
     * @param count
     *          大于0，表示删除从左往右数，值为value的第一个数据
     *          小于0，表示删除从右往左数，值为value的第一个数据
     *          等于0，表示删除值为value的所有数据
     * @param value 被删除的数据
     * @return
     */
    public static Long remove(String key, long count, Object value) {
        return remove(defaultDB , key , count , value);
    }
    public static Long remove(int dbIndex ,String key, long count, Object value) {
        return knife4jRedisManager.redisTemplate(dbIndex).opsForList().remove(key, count , value);
    }

}
